#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->stackedWidget->setCurrentWidget(ui->pagMain);

    //初始化statulLabel
    statueLabel =  new QLabel(this);
    statueLabel->setText("当前二值化阈值: 30");
    ui->statusbar->addWidget(statueLabel);

    //初始化二值化阈值为30,最大为255
    binValue = 30;

    //大部分按钮初始默认不可操作,等打开照片后才能操作
    ui->actHistogram->setEnabled(false);
    ui->act3x3medianFilter->setEnabled(false);
    ui->actiAverageFilter->setEnabled(false);
    ui->actBinaryzation->setEnabled(false);
    ui->actLaplace->setEnabled(false);
    ui->actOring->setEnabled(false);
    ui->actEdgeDetection->setEnabled(false);
    ui->actSave->setEnabled(false);
    ui->actGray->setEnabled(false);
    ui->actBGRHis->setEnabled(false);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::fillMainLabel()
{
    cv::Mat aMat = theMat;
    cv::Mat temp;
    if(aMat.channels() == 4){
        cv::cvtColor(aMat,temp,cv::COLOR_BGRA2RGB);
    }
    else if(aMat.channels() == 3){
        cv::cvtColor(aMat,temp,cv::COLOR_BGR2RGB);
    }else {
        cv::cvtColor(aMat,temp,cv::COLOR_GRAY2RGB);
    }

    theMat = temp;

    QImage img = QImage((uchar*)temp.data,temp.cols,temp.rows,temp.step,QImage::Format_RGB888);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));
//    ui->labMain->resize(ui->labMain->pixmap()->size());
}


void MainWindow::on_actAbout_triggered()
{
    aboutDialog *a = new aboutDialog;//创建关于本软件临时对话框指针
    a->exec();//模态显示对话框,在本对话框关闭前不可操作主窗口
    delete a;//用户退出或关闭对话框时删除此对话框指针
}


void MainWindow::on_actQuit_triggered()
{
    this->close();//点击退出按钮后先隐藏程序对话框

}


void MainWindow::on_actOpen_triggered()
{
    QString str;
    str = QFileDialog::getOpenFileName(0,"请选择图片",QDir::homePath(),"所有文件(*.*);;jpg(*.jpg);;png(*.png);;bmp(*.bmp)");
    if(str.isEmpty()||str.isNull()){
        QMessageBox::warning(0,"警告","未选择图片.");
        return;
    }
    //    ui->labMain->setText(str);
    openPixPath = str;
    theMat = cv::imread(str.toStdString());
    //    cv::imshow("csyx",theMat);
    fillMainLabel();

    ui->actHistogram->setEnabled(true);
    ui->act3x3medianFilter->setEnabled(true);
    ui->actiAverageFilter->setEnabled(true);
    ui->actBinaryzation->setEnabled(true);
    ui->actLaplace->setEnabled(true);
    ui->actOring->setEnabled(true);
    ui->actEdgeDetection->setEnabled(true);
    ui->actSave->setEnabled(true);
    ui->actGray->setEnabled(true);
    ui->actBGRHis->setEnabled(true);


    currentMat = theMat;
    currentFormat = QImage::Format_RGB888;
    ui->stackedWidget->setCurrentWidget(ui->pagMain);
}


void MainWindow::on_actSave_triggered()
{
    if(ui->stackedWidget->currentIndex() == ui->stackedWidget->indexOf(ui->pagMain)){
        QString savePath;
        savePath = QFileDialog::getSaveFileName(0,"请选择图片保存路径",QDir::homePath(),"jpg(*.jpg);;png(*.png);;bmp(*.bmp);;所有文件(*.*)");
        if(savePath.isNull() || savePath.isEmpty()){
            QMessageBox::warning(0,"警告","未选择保存位置.");
            return;
        }

        QImage img = this->ui->labMain->pixmap()->toImage().scaled(QImage(openPixPath).size(),Qt::KeepAspectRatio, Qt::SmoothTransformation);
        if(img.save(savePath) == true){
            QMessageBox::information(0,"提示","图片保存成功.");
        }
    }else if(ui->stackedWidget->currentIndex() == ui->stackedWidget->indexOf(ui->pagHis)){
        QString savePath;
        savePath = QFileDialog::getSaveFileName(0,"请选择图片保存路径",QDir::homePath(),"jpg(*.jpg);;png(*.png);;bmp(*.bmp);;所有文件(*.*)");
        if(savePath.isNull() || savePath.isEmpty()){
            QMessageBox::warning(0,"警告","未选择保存位置.");
            return;
        }

        QImage img = this->ui->labHis->pixmap()->toImage().scaled(QImage(openPixPath).size(),Qt::KeepAspectRatio, Qt::SmoothTransformation);
        if(img.save(savePath) == true){
            QMessageBox::information(0,"提示","图片保存成功.");
        }
    }
}


void MainWindow::on_actGray_triggered()
{
    cv::Mat temp;
    temp = theMat;
    cv::cvtColor(temp,temp,cv::COLOR_BGR2GRAY);
//    cv::imwrite(openPixPath.toStdString(),temp);
    QImage img = QImage((uchar*)temp.data,temp.cols,temp.rows,temp.step,QImage::Format_Grayscale8);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

    currentMat = temp;

    currentFormat = QImage::Format_Grayscale8;
    ui->stackedWidget->setCurrentWidget(ui->pagMain);
}


void MainWindow::on_actBinaryzation_triggered()
{
    cv::Mat temp;
    temp = theMat;
    cv::cvtColor(temp,temp,cv::COLOR_BGR2GRAY);
//    cv::imwrite(openPixPath.toStdString(),temp);
    cv::Mat bin;
    cv::threshold(temp,bin,binValue,255,cv::THRESH_BINARY);


    QImage img = QImage((uchar*)bin.data,bin.cols,bin.rows,bin.step,QImage::Format_Grayscale8);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

    currentMat = bin;
    currentFormat = QImage::Format_Grayscale8;
    ui->stackedWidget->setCurrentWidget(ui->pagMain);
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    QImage img = QImage((uchar*)currentMat.data,currentMat.cols,currentMat.rows,currentMat.step,currentFormat);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));
}


void MainWindow::on_actOring_triggered()
{
    cv::Mat aMat = cv::imread(openPixPath.toStdString());

    if(aMat.channels() == 4){
        cv::cvtColor(aMat,theMat,cv::COLOR_BGRA2RGB);
    }
    else if(aMat.channels() == 3){
        cv::cvtColor(aMat,theMat,cv::COLOR_BGR2RGB);
    }else {
        cv::cvtColor(aMat,theMat,cv::COLOR_GRAY2RGB);
    }

    currentMat = theMat;
    currentFormat = QImage::Format_RGB888;


    QImage img = QImage((uchar*)currentMat.data,currentMat.cols,currentMat.rows,currentMat.step,currentFormat);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

    ui->stackedWidget->setCurrentWidget(ui->pagMain);
}


void MainWindow::on_actiAverageFilter_triggered()
{
    cv::Mat temp;
    temp = theMat;

    cv::blur(temp,temp,cv::Size(3,3));

    QImage img = QImage((uchar*)temp.data,temp.cols,temp.rows,temp.step,QImage::Format_RGB888);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

    currentMat = temp;
    currentFormat = QImage::Format_RGB888;
    ui->stackedWidget->setCurrentWidget(ui->pagMain);
}


void MainWindow::on_act3x3medianFilter_triggered()
{
    cv::Mat temp;
    temp = theMat;

    cv::medianBlur(temp,temp,5);

    QImage img = QImage((uchar*)temp.data,temp.cols,temp.rows,temp.step,QImage::Format_RGB888);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

    currentMat = temp;
    currentFormat = QImage::Format_RGB888;
    ui->stackedWidget->setCurrentWidget(ui->pagMain);
}


void MainWindow::on_actLaplace_triggered()
{
    cv::Mat temp;
    temp = theMat;

    cv::Laplacian(temp,temp,-1,3);

    QImage img = QImage((uchar*)temp.data,temp.cols,temp.rows,temp.step,QImage::Format_RGB888);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

    currentMat = temp;
    currentFormat = QImage::Format_RGB888;
    ui->stackedWidget->setCurrentWidget(ui->pagMain);
}


void MainWindow::on_actEdgeDetection_triggered()
{
    cv::Mat temp;
    temp = theMat;

    cv::Sobel(temp,temp,-1,1,1);

    QImage img = QImage((uchar*)temp.data,temp.cols,temp.rows,temp.step,QImage::Format_RGB888);
    ui->labMain->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

    currentMat = temp;
    currentFormat = QImage::Format_RGB888;
    ui->stackedWidget->setCurrentWidget(ui->pagMain);
}


void MainWindow::on_actSetBinValue_triggered()
{
    int value;
    value = QInputDialog::getInt(0,"设置二进制阈值","请输入0到255之间的值作为二值化阈值:",binValue);
    if(value<0||value>255){
        QMessageBox::warning(0,"警告","数值不合理!");
        return;
    }
    binValue = value;
    this->statueLabel->setText("当前二值化阈值: "+ QString::asprintf("%d",binValue));
}


void MainWindow::on_actHistogram_triggered()
{
    const int channels[] = { 0 };
    cv::Mat hist;//定义输出Mat类型
    int dims = 1;//设置直方图维度
    const int histSize[] = { 256 }; //直方图每一个维度划分的柱条的数目
    //每一个维度取值范围
    float pranges[] = { 0, 255 };//取值区间
    const float* ranges[] = { pranges };

    cv::Mat gray = currentMat;
    calcHist(&gray, 1, channels, cv::Mat(), hist, dims, histSize, ranges, true, false);//计算直方图

    int hist_w = 500;
    int hist_h = 300;
    int nHistSize = 256;
    int bin_w = cvRound((double)hist_w / nHistSize);	//区间
    cv::Mat histImage(hist_h, hist_w, CV_8UC3, cv::Scalar(0, 0, 0));//创建一个黑底的8位的3通道图像，高300，宽500
    normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());//将直方图归一化到[0,histImage.rows]
    for (int i = 1; i < nHistSize; i++)
    {
        line(histImage, cv::Point(bin_w*(i - 1), hist_h - cvRound(hist.at<float>(i - 1))),cv::Point(bin_w*(i), hist_h - cvRound(hist.at<float>(i))), cv::Scalar(255, 0, 0));
    }

    QImage img = QImage((uchar*)histImage.data,histImage.cols,histImage.rows,histImage.step,QImage::Format_RGB888);
    ui->labHis->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

    currentMat = histImage;
    currentFormat = QImage::Format_RGB888;
    ui->stackedWidget->setCurrentWidget(ui->pagHis);
}


void MainWindow::on_actBGRHis_triggered()
{

    std::vector<cv::Mat>bgr;
        split(theMat, bgr);

        //2、定义直方图的区间数
        int numbers = 256;

        //3、定义变量范围并创建3个矩阵来存储每个直方图
        float range[] = { 0,256 };
        const float* histRange = { range };
        cv::Mat b_hist, g_hist, r_hist;

        //4、使用calcHist函数计算直方图
        int numbins = 256;
        calcHist(&bgr[0], 1, 0, cv::Mat(), b_hist, 1, &numbins, &histRange);
        calcHist(&bgr[1], 1, 0, cv::Mat(), g_hist, 1, &numbins, &histRange);
        calcHist(&bgr[2], 1, 0, cv::Mat(), r_hist, 1, &numbins, &histRange);

        //5、创建一个512*300像素大小的彩色图像，用于绘制显示
        int width = 512;
        int height = 300;
        cv::Mat histImage(height, width, CV_8UC3, cv::Scalar(20, 20, 20));

        //6、将最小值与最大值标准化直方图矩阵
        normalize(b_hist, b_hist, 0, height, cv::NORM_MINMAX);
        normalize(g_hist, g_hist, 0, height, cv::NORM_MINMAX);
        normalize(r_hist, r_hist, 0, height, cv::NORM_MINMAX);

        //7、使用彩色通道绘制直方图
        int binStep = cvRound((float)width / (float)numbins);  //通过将宽度除以区间数来计算binStep变量

        for (int i = 1; i < numbins; i++)
        {
            line(histImage,
                cv::Point(binStep * (i - 1), height - cvRound(b_hist.at<float>(i - 1))),
                cv::Point(binStep * (i), height - cvRound(b_hist.at<float>(i))),
                cv::Scalar(255, 0, 0)
            );
            line(histImage,
                cv::Point(binStep * (i - 1), height - cvRound(g_hist.at<float>(i - 1))),
                cv::Point(binStep * (i), height - cvRound(g_hist.at<float>(i))),
                cv::Scalar(0, 255, 0)
            );
            line(histImage,
                cv::Point(binStep * (i - 1), height - cvRound(r_hist.at<float>(i - 1))),
                cv::Point(binStep * (i), height - cvRound(r_hist.at<float>(i))),
                cv::Scalar(0, 0, 255)
            );
        }



        QImage img = QImage((uchar*)histImage.data,histImage.cols,histImage.rows,histImage.step,QImage::Format_RGB888);
        ui->labHis->setPixmap(QPixmap::fromImage(img).scaledToHeight(ui->labMain->height()));

        currentMat = histImage;
        currentFormat = QImage::Format_RGB888;

        ui->stackedWidget->setCurrentWidget(ui->pagHis);
}

